////////////////////////////////////////////////
//	File			:	"ObjectManager.h"
//
//	Author			:	Steven Seufert (SMS)
//	Based in part on: the CSGD_ObjectManager written by David Brown
//			
//	Last Modified	:	January 14, 2012
//
//	Purpose			:	To contain and manage all of our game objects in one location.
/////////////////////////////////////////////////
#ifndef OBJECT_MANAGER_H
#define OBJECT_MANAGER_H

#ifndef VECTOR_
#define VECTOR_
#include <vector>
using std::vector;
#endif

#include <iostream>
using namespace std;

#include "IBaseInterface.h"

class CObjectManager
{
private:
	vector<IBaseInterface*> m_vObjectList[4];		// an array of IBaseInterface* vectors; each element in the array is a different grouping of vectors

	/*
		Render Layers
		0 - world tiles
		1 -  reserved; not used
		2 - spells/particles rendered beneath characters
		3 - players, enemies, most spells
		4 - spells/particles rendered above characters
		5 -  reserved; not used
		6 - HUD
		7 - HUD 2
		8 - cursors
		9 -  reserved; not used
	*/
	vector<IBaseInterface*> m_vRenderList[10];		// an array of IBaseInterface* vectors; each element in the array is a different layer of objects

	// the instance to our singleton
	//static CObjectManager* sm_Instance;
	
	// constructor
	CObjectManager(void);
	
	// destructor
	~CObjectManager(void) {}

	// copy constructor
	CObjectManager(const CObjectManager&);

	// assignment operator
	CObjectManager& operator=(const CObjectManager&);
public:
	// call the instance to our singleton
	static CObjectManager* GetInstance(void);

	// delete the instance of our singleton
	static void DeleteInstance(void);

	///////////////////////////////////////////////////
	//	Function	:	"UpdateObjects"
	//	
	//	Last Modified:	January 14, 2012
	//
	//	Input		:	fElapsedTime	-	the amount of time in seconds that has passed since the last frame
	//					group			-	combination of flags for which specific groups you want to update 
	//										(OMF_PLAYER, OMF_ENEMY, OMF_SPELL, OMF_ENVOBJECT, OMF_ALL)
	//
	//	Return		:	none
	//
	//	Purpose		:	To update all the objects in a specific group (or all objects)
	//////////////////////////////////////////////////
	void UpdateObjects(float fElapsedTime, unsigned int group);

	///////////////////////////////////////////////////
	//	Function	:	"RenderObjectsByLayer"
	//	
	//	Last Modified:	February 25, 2012
	//
	//	Input		:	none
	//										
	//	Return		:	none
	//
	//	Purpose		:	To render all the objects in ascending layer order
	//////////////////////////////////////////////////
	void RenderObjectsByLayer();

	///////////////////////////////////////////////////
	//	Function	:	"RenderObjectsByGroup"
	//	
	//	Last Modified:	January 14, 2012
	//
	//	Input		:	group			-	combination of flags for which specific groups you want to update 
	//										(OMF_PLAYER, OMF_ENEMY, OMF_SPELL, OMF_ENVOBJECT, OMF_ALL)
	//										
	//	Return		:	none
	//
	//	Purpose		:	To render all the objects in a specific group (or all objects)
	//////////////////////////////////////////////////
	void RenderObjectsByGroup(unsigned int group);

	///////////////////////////////////////////////////
	//	Function	:	"AddObject"
	//	
	//	Last Modified:	January 14, 2012
	//
	//	Input		:	pObject			-	a pointer to the object you want to add to the object manager
	//					group			-	flag for which specific group you want to place the object in
	//										(OMF_PLAYER, OMF_ENEMY, OMF_SPELL, OMF_ENVOBJECT)
	//					renderLayer		-	the render layer at which you wish the object to be rendered
	//										
	//	Return		:	none
	//
	//	Purpose		:	To add an object to a specific group 
	//
	//	Notes		:	The function will exit without adding the object if the flag OMF_ALL is used.
	//					A specified group must be sent to actually add the object
	//					The function will exit if a null pointer is passed
	//					Adding more than one flag may result in the object being added to an unwanted group
	//////////////////////////////////////////////////
	void AddObject(IBaseInterface* pObject, unsigned int group, int renderLayer);

	///////////////////////////////////////////////////
	//	Function	:	"RemoveObject"
	//	
	//	Last Modified:	January 14, 2012
	//
	//	Input		:	pObject			-	a pointer to the object you want to remove to the from the object manager
	//										
	//	Return		:	none
	//
	//	Purpose		:	To remove an object from the object manager
	//////////////////////////////////////////////////
	void RemoveObject(IBaseInterface* pObject);

	///////////////////////////////////////////////////
	//	Function	:	"GetSize"
	//	
	//	Last Modified:	January 14, 2012
	//
	//	Input		:	group			-	combination of flags for which specific groups you want to query for size
	//										(OMF_PLAYER, OMF_ENEMY, OMF_SPELL, OMF_ENVOBJECT, OMF_ALL)
	//										
	//	Return		:	the total number of objects in the object manager group(s)
	//
	//	Purpose		:	To return the total number of objects in the object manager group(s)
	//////////////////////////////////////////////////
	int GetSize(unsigned int group) const;

	///////////////////////////////////////////////////
	//	Function	:	"GetSizeOfLayer"
	//	
	//	Last Modified:	February 25, 2012
	//
	//	Input		:	layer			-	the layer whose size you wish to obtain
	//										Pass NUM_RENDER_LAYERS to get the number of all render objects
	//										
	//	Return		:	the total number of objects in the object manager render layer
	//
	//	Purpose		:	To return the total number of objects in the object manager render layer
	//////////////////////////////////////////////////
	int GetSizeOfLayer(unsigned int layer) const;

	///////////////////////////////////////////////////
	//	Function	:	"RemoveAllObjects"
	//	
	//	Last Modified:	January 14, 2012
	//
	//	Input		:	none
	//										
	//	Return		:	none
	//
	//	Purpose		:	Removes all objects in the entire object manager
	//////////////////////////////////////////////////
	void RemoveAllObjects(void);

	///////////////////////////////////////////////////
	//	Function	:	"CheckCollisions"
	//	
	//	Last Modified:	January 14, 2012
	//
	//	Input		:	groupOne		-	the specific group of objects you want to check against group two's objects
	//					groupTwo		-	the specific group of objects you want to groupOne to check against
	//										(OMF_PLAYER, OMF_ENEMY, OMF_SPELL, OMF_ENVOBJECT)
	//										
	//	Return		:	none
	//
	//	Purpose		:	To run every object's CheckCollision() in group one against every object in group two
	//
	//	Notes		:	There is no ALL!
	//////////////////////////////////////////////////
	void CheckCollisions(unsigned int groupOne, unsigned int groupTwo);

	///////////////////////////////////////////////////
	//	Function	:	"CheckAllCollisions"
	//	
	//	Last Modified:	January 14, 2012
	//										
	//	Return		:	none
	//
	//	Purpose		:	To check collisions of each object against all other objects
	//
	// Notes		:	Environmental objects are not checked against environmental objects because they don't move
	//////////////////////////////////////////////////
	void CheckAllCollisions();

	///////////////////////////////////////////////////
	//	Function	:	"PrintObjectsToConsole"
	//	
	//	Last Modified:	January 14, 2012
	//
	//	Input		:	group			-	combination of flags for which specific groups you want to query for size
	//										(OMF_PLAYER, OMF_ENEMY, OMF_SPELL, OMF_ENVOBJECT, OMF_ALL)
	//										
	//	Return		:	none
	//
	//	Purpose		:	Prints the object class type IDs for each object in the manager to the console
	//////////////////////////////////////////////////
	void PrintObjectsToConsole(unsigned int group);
};
#endif